package com.hundsun.cprs.yyt.service.trade.service.impl;

import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.exception.ServiceCodeException;
import com.hundsun.cprs.yyt.service.account.domain.Account;
import com.hundsun.cprs.yyt.service.account.service.AccountService;
import com.hundsun.cprs.yyt.service.common.Constants;
import com.hundsun.cprs.yyt.service.common.dto.UserAccountDTO;
import com.hundsun.cprs.yyt.service.common.service.RemoteUserService;
import com.hundsun.cprs.yyt.service.goods.domain.Goods;
import com.hundsun.cprs.yyt.service.goods.dto.GoodsInfo;
import com.hundsun.cprs.yyt.service.goods.service.GoodsService;
import com.hundsun.cprs.yyt.service.system.enums.EnumBussinessParam;
import com.hundsun.cprs.yyt.service.system.service.BusinessParamHelper;
import com.hundsun.cprs.yyt.service.system.service.BussinessParamService;
import com.hundsun.cprs.yyt.service.trade.dao.EntrustImportLogDao;
import com.hundsun.cprs.yyt.service.trade.dao.TradeEntrustDao;
import com.hundsun.cprs.yyt.service.trade.domain.EntrustImportLog;
import com.hundsun.cprs.yyt.service.trade.domain.TradeEntrust;
import com.hundsun.cprs.yyt.service.trade.domain.query.EntrustImportLogQuery;
import com.hundsun.cprs.yyt.service.trade.enums.*;
import com.hundsun.cprs.yyt.service.trade.service.EntrustImportLogService;
import com.hundsun.cprs.yyt.util.DoubleUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * 委托单批量导入处理接口
 * @author herong22384
 * @date 2019/8/13 19:33
 */
@Service
public class EntrustImportLogServiceImpl extends BaseService implements EntrustImportLogService {

    public static final String YYT_ENTRUST_IMPORT_LOCK = Constants.YYT_ENTRUST_IMPORT_LOCK;

    @Autowired
    private EntrustImportLogDao logDao;
    @Autowired
    @Qualifier("commonThreadPool")
    private Executor executor;
    @Autowired
    private TradeEntrustDao entrustDao;
    @Autowired
    private BussinessParamService systemParam;
    @Autowired
    private AccountService accountService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void batchInsert(List<EntrustImportLog> datas) {
        if (!CollectionUtils.isEmpty(datas)){
            logDao.batchInsert(datas);
        }
    }

    @Override
    public void queryByPage(EntrustImportLogQuery query) {
        List<EntrustImportLog> logs = logDao.queryByPage(query);
        query.compatible(logs);
    }

    @Override
    public void handleBatchEntrust() {
        //异步处理导入记录
        executor.execute(new Runnable() {
            public void run() {
                try{
                    while (true){
                        EntrustImportLogQuery query = new EntrustImportLogQuery();
                        query.setStatus(0);
                        query.setPageNo(1);
                        query.setPageSize(5000);
                        queryByPage(query);

                        if (query.getTotalCount() == 0){
                            break;
                        }

                        //更新该批数据状态为处理中
                        logDao.updateStatusByBatch(query.getData(), 1,"处理中");

                        //处理挂售单批量导入
                        doBatchEntrustImport(query.getData());
                    }
                }finally {
                    //本次全部处理完成需要释放reids锁
                    redisTemplate.delete(YYT_ENTRUST_IMPORT_LOCK);
                }
            }
        });
    }

    protected void doBatchEntrustImport(List<EntrustImportLog> datas){
        List<TradeEntrust> entrusts = new ArrayList<>();
        List<EntrustImportLog> logs = new ArrayList<>();

        //1.db重复订单编号的委托单校验
        removeRepeatOrderSn(datas);

        for (EntrustImportLog log : datas){
            try{
                //2.本批次内存去除重复订单
                if (removeRepeatOrderSn(entrusts,log)){
                    log.setStatus(-1);
                    log.setRemark("订单编号在数据库中已存在");
                    logDao.updateByPrimaryKeySelective(log);
                    continue;
                }

                //3.校验会员信息是否正常
                Account user = accountService.getAccountByFundAccountFromCache(log.getFundAccount());
                if (user == null){
                    log.setStatus(-1);
                    log.setRemark("会员信息不存在");
                    logDao.updateByPrimaryKeySelective(log);
                    continue;
                }

                //4.校验商品信息是否正常
                GoodsInfo goods = goodsService.getGoodsInfoByGoodsCodeFromCache(log.getGoodsCode());
                if (goods == null){
                    log.setStatus(-1);
                    log.setRemark("商品信息不存在");
                    logDao.updateByPrimaryKeySelective(log);
                    continue;
                }

                //5.组装委托单信息
                TradeEntrust entrust = new TradeEntrust();
                fillEntrust(entrust,log,user,goods);
                entrusts.add(entrust);
                logs.add(log);
            }catch (ServiceCodeException e){
                log.setStatus(-1);
                log.setRemark(e.getErrorDesc());
                logDao.updateByPrimaryKeySelective(log);
                logger.error(e);
            }catch (Exception e){
                log.setStatus(-1);
                log.setRemark("数据异常，处理失败");
                logDao.updateByPrimaryKeySelective(log);
                logger.error(e);
            }
        }

        if (!CollectionUtils.isEmpty(entrusts)){
            //6.批量插入委托单
            entrustDao.batchInsert(entrusts);
        }
        if (!CollectionUtils.isEmpty(logs)){
            //7.批量更新记录状态为处理已完成
            logDao.updateStatusByBatch(logs,2,"处理成功");
        }
    }

    protected void fillEntrust(TradeEntrust entrust,EntrustImportLog log,Account user,Goods goods){
        //组装委托单信息
        entrust.setOrderSn(log.getOrderSn());
        entrust.setGoodsCode(goods.getGoodsCode());
        entrust.setGoodsId(goods.getId().longValue());
        entrust.setEntrustAmount(new Long(log.getAmount()));
        entrust.setFundAccount(log.getFundAccount());
        entrust.setUserId(user.getUserId());
        entrust.setUserName(user.getUserName());
        entrust.setEntrustBs(EnumEntustBSType.SELL.getCode().toString());
        Double buyPrice = new BigDecimal(Double.parseDouble(log.getBuyPrice())).multiply(new BigDecimal(100)).doubleValue();
        entrust.setEntrustPrice(buyPrice.longValue());
        entrust.setEntrustNo(entrustDao.getEntrustNoFromSequence());
        entrust.setEntrustStatus(EnumTradeEntrustStatus.INIT.getStatus());
        entrust.setStatus(EnumTradeStatus.INIT.getStatus());
        //默认为都是批量导入的挂单，用于区分正常挂售进来的委托单
        entrust.setEntrustFrom(EnumEntustFrom.BATCH_INSERT.getCode());
        //默认都是老用户标签
        entrust.setEntrustTag(EnumEntustTag.OLD_USER.getCode());
        // TODO:获取全局交易手续费及综合管理费比例
        entrust.setCommissionRate(BusinessParamHelper.getIntValue(systemParam, EnumBussinessParam.COMMISSION_RATE));
        entrust.setManagementRate(BusinessParamHelper.getIntValue(systemParam, EnumBussinessParam.MANAGEMENT_RATE));
        entrust.setCommissionFund(BigDecimal.ZERO.longValue());
        entrust.setManagementFund(BigDecimal.ZERO.longValue());
        entrust.setBusinessFund(BigDecimal.ZERO.longValue());
        entrust.setTotalBusinessFund(BigDecimal.ZERO.longValue());
        entrust.setGainBusinessFund(BigDecimal.ZERO.longValue());
        entrust.setBusinessAmount(BigDecimal.ZERO.longValue());
        //由于审核功能，此处直接将挂售时间置为申请时间，审核上报时不再修改挂售时间
        entrust.setEntrustTime(new Date());
    }

    protected void removeRepeatOrderSn(List<EntrustImportLog> datas){
        //本批次db委托表去重
        List<EntrustImportLog> entrusts = logDao.getListByOrderSn(datas);
        if (!CollectionUtils.isEmpty(entrusts)){
            for (EntrustImportLog log : entrusts){
                for (EntrustImportLog data : datas){
                    if (data.getOrderSn().equals(log.getOrderSn())){
                        datas.remove(data);
                        break;
                    }
                }
                log.setStatus(-1);
                log.setRemark("订单编号在数据库中已存在");
                logDao.updateByPrimaryKeySelective(log);
                continue;
            }
        }
    }

    protected Boolean removeRepeatOrderSn(List<TradeEntrust> entrusts,EntrustImportLog log){
        //本批次内存去重
        if (CollectionUtils.isEmpty(entrusts)){
            return false;
        }
        for (TradeEntrust entrust : entrusts){
            if (entrust.getOrderSn().equals(log.getOrderSn())){
                return true;
            }
        }
        return false;
    }
}
